package com.woniuxy.consumer.student.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.woniuxy.common.DTO.ResponseResult;
import com.woniuxy.common.entity.Student;
import com.woniuxy.consumer.student.feignClients.StudentOpenfeign;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.function.Supplier;

/**
 * @Author: linKe
 * @Date: 2022/1/20 9:48
 * @FileName: EurekaConsumerStudentController
 * @version: 1.0
 * @Description: 改造成eureka注册中心调用服务
 * <p>
 * 学生消费服务调用类
 * 远程调用8081项目
 * <p>
 * openfeign 方式调用
 * / @RefreshScope,添加自动刷新注释一定要添加在controller上
 */
@RefreshScope
@DefaultProperties(defaultFallback = "consumerTimeoutFallback")
@Slf4j
@Api(tags = {"消费者", "调用方"}, value = "调用学生类")
@RestController
@RequestMapping("/openfeign/consumerStudent")
public class OpenfeignConsumerStudentController {
    @Autowired
    StudentOpenfeign studentOpenfeign;


    @GetMapping("/{id}")
    public ResponseResult<Student> getStudentById(@PathVariable("id") int id) {
        // restTemplate的API 实现远程调用
        return studentOpenfeign.getStudentById(id);
    }

    @GetMapping("/")
    public ResponseResult<List<Student>> getStudentAll() {
        // restTemplate的API 实现远程调用
        return studentOpenfeign.getStudent();
    }

    @PostMapping("/")
    public ResponseResult<?> addStudent(@RequestBody Student student) {
        // restTemplate的API 实现远程调用
        return studentOpenfeign.addStudent(student);
    }

    @ApiOperation("分页查询")
    @GetMapping("/{pageIndex}/{pageSize}")
    public ResponseResult<?> getStudentPage(@PathVariable("pageIndex") int pageIndex,
                                            @PathVariable("pageSize") int pageSize,
                                            @RequestBody Student student) {
        // restTemplate的API 实现远程调用
        return studentOpenfeign.addStudent(student);
    }

    @ApiOperation("服务降级测试")
    @GetMapping("/ok")
    public ResponseResult<?> ok() {

        return studentOpenfeign.timeout();
    }

    @ApiOperation("超时异常测试")
    @GetMapping("/timeout")
    public ResponseResult<?> timeout() {
        try{
            // 模拟异常处理 只针对当前服务有效，还是会拖慢其他服务的访问
            // 不解决实际问题
            return studentOpenfeign.timeout();

        }catch (Exception e){
            return new ResponseResult<String>(500,"超时异常处理","timeoutException");
        }
    }

    @ApiOperation("超时异常测试,定义调用当前方法如果出现异常，执行的降级方法，降级的处理方法的名字的方法签名一致（返回值，参数列表，访问修饰符）" +
            "使用统一降级方法，不用指定属性" +
            "缺点：方法签名要统一不好满足，参数不好统一！")
    /// @HystrixCommand(fallbackMethod = "timeoutFallback")
   // @HystrixCommand
    @GetMapping("/timeout1")
    public ResponseResult<?> timeout1() {
            log.info("进入timeout1");
            return studentOpenfeign.timeout();
    }



    public ResponseResult<?> timeoutFallback() {

        log.info("进入timeoutFallback");
        return new ResponseResult<String>(500, "超时异常处理", "timeoutException");
    }


    @ApiOperation("统一的降级处理")
    public ResponseResult<?> consumerTimeoutFallback() {

        log.info("consumerTimeoutFallback");
        return new ResponseResult<String>(500, "统一降级处理，超时异常处理", "consumerTimeoutFallback");
    }


    @HystrixCommand(fallbackMethod = "testFallback",commandProperties = {
            @HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE")
    })
    @GetMapping("/test/{id}")
    public ResponseResult<?> test(@PathVariable("id") int id) {
        if (id<2){
            throw  new RuntimeException("testException");
        }
        log.info("进入timeout1");
        return new ResponseResult<String>(200, "ok", "consumerTimeoutFallback");

    }


    @ApiOperation("测试熔断参数配置")
    public ResponseResult<?> testFallback() {

        log.info("testFallback");
        return new ResponseResult<String>(500, "熔断参数配置，超时异常处理", "testFallback");
    }



    @Value("${testConfig}")
    String testConfig;

    @ApiOperation("测试熔断参数配置")
    @GetMapping("/testConfig")
    public ResponseResult<?> testConfig() {

        log.info("testFallback");
        return new ResponseResult<String>(500, "读取参数", testConfig);
    }
}
